bitkeeper revision 1.1236.1.183 (424d1ccaDlUUQZ1KrVHubRYFS5AKQA)
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 1 Apr 2005 10:04:58 +0000 (10:04 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 1 Apr 2005 10:04:58 +0000 (10:04 +0000)
Batch p.t. pin requests during guest restore (after being suspended, or
after migration). Allow L1 tables to be pinned even after their va
backptr is fixed (no longer mutable).
Signed-off-by: Keir Fraser <keir@xensource.com>
tools/libxc/xc_linux_restore.c
tools/libxc/xc_private.c
tools/libxc/xc_private.h
xen/arch/x86/mm.c

index 220890d3461a9cb6b5e989c7eecf5ce79592e9ef..79f0c6ac455ac8f3bad0d0ae7283c0160bf914ae 100644 (file)
@@ -106,6 +106,10 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
     /* used by debug verify code */
     unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
 
+#define MAX_PIN_BATCH 1024
+    struct mmuext_op pin[MAX_PIN_BATCH];
+    unsigned int nr_pins = 0;
+
     xcio_info(ioctxt, "xc_linux_restore start\n");
 
     if ( mlock(&ctxt, sizeof(ctxt) ) )
@@ -414,38 +418,33 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
 
     xcio_info(ioctxt, "Received all pages\n");
 
+    if ( finish_mmu_updates(xc_handle, mmu) )
+        goto out;
+
     /*
      * Pin page tables. Do this after writing to them as otherwise Xen
      * will barf when doing the type-checking.
      */
     for ( i = 0; i < nr_pfns; i++ )
     {
+        if ( (pfn_type[i] & LPINTAB) == 0 )
+            continue;
         if ( pfn_type[i] == (L1TAB|LPINTAB) )
+            pin[nr_pins].cmd = MMUEXT_PIN_L1_TABLE;
+        else /* pfn_type[i] == (L2TAB|LPINTAB) */
+            pin[nr_pins].cmd = MMUEXT_PIN_L2_TABLE;
+        pin[nr_pins].mfn = pfn_to_mfn_table[i];
+        if ( ++nr_pins == MAX_PIN_BATCH )
         {
-            if ( pin_table(xc_handle, MMUEXT_PIN_L1_TABLE,
-                           pfn_to_mfn_table[i], dom) ) {
-                printf("ERR pin L1 pfn=%lx mfn=%lx\n",
-                       (unsigned long)i, pfn_to_mfn_table[i]);
-                goto out;
-            }
-        }
-    }
-
-    /* must pin all L1's before L2's (need consistent va back ptr) */
-    for ( i = 0; i < nr_pfns; i++ )
-    {
-        if ( pfn_type[i] == (L2TAB|LPINTAB) )
-        {
-            if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE,
-                           pfn_to_mfn_table[i], dom) ) {
-                printf("ERR pin L2 pfn=%lx mfn=%lx\n",
-                       (unsigned long)i, pfn_to_mfn_table[i]);
+            if ( do_mmuext_op(xc_handle, pin, nr_pins, dom) < 0 )
                 goto out;
-            }
+            nr_pins = 0;
         }
     }
 
-    if ( finish_mmu_updates(xc_handle, mmu) ) goto out;
+    if ( (nr_pins != 0) &&
+         (do_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) )
+        goto out;
 
     xcio_info(ioctxt, "\b\b\b\b100%%\n");
     xcio_info(ioctxt, "Memory reloaded.\n");
index 386a240178f364cb50d12c8b81ea7ce27be86a67..15327ccdbb1de7eefbe4bdf25d92c6ef94e22f1e 100644 (file)
@@ -95,36 +95,15 @@ unsigned int get_pfn_type(int xc_handle,
 int pin_table(
     int xc_handle, unsigned int type, unsigned long mfn, domid_t dom)
 {
-    int err = 0;
     struct mmuext_op op;
-    privcmd_hypercall_t hypercall;
 
     op.cmd = type;
     op.mfn = mfn;
 
-    hypercall.op     = __HYPERVISOR_mmuext_op;
-    hypercall.arg[0] = (unsigned long)&op;
-    hypercall.arg[1] = 1;
-    hypercall.arg[2] = 0;
-    hypercall.arg[3] = dom;
-
-    if ( mlock(&op, sizeof(op)) != 0 )
-    {
-        PERROR("Could not lock mmuext_op");
-        err = 1;
-        goto out;
-    }
-
-    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
-    {
-        ERROR("Failure when submitting mmu updates");
-        err = 1;
-    }
+    if ( do_mmuext_op(xc_handle, &op, 1, dom) < 0 )
+        return 1;
 
-    (void)munlock(&op, sizeof(op));
-
- out:
-    return err;
+    return 0;
 }
 
 static int flush_mmu_updates(int xc_handle, mmu_t *mmu)
index 78f8bbe194c5c528976bb0513718b6969e980a9e..8445e75fbeee71c7669fa032bcd238df86fdb837 100644 (file)
@@ -142,6 +142,38 @@ static inline int do_dom_mem_op(int            xc_handle,
  out1: return ret;
 }    
 
+static inline int do_mmuext_op(
+    int xc_handle,
+    struct mmuext_op *op,
+    unsigned int nr_ops,
+    domid_t dom)
+{
+    privcmd_hypercall_t hypercall;
+    long ret = -EINVAL;
+       
+    hypercall.op     = __HYPERVISOR_mmuext_op;
+    hypercall.arg[0] = (unsigned long)op;
+    hypercall.arg[1] = (unsigned long)nr_ops;
+    hypercall.arg[2] = (unsigned long)0;
+    hypercall.arg[3] = (unsigned long)dom;
+
+    if ( mlock(op, nr_ops*sizeof(*op)) != 0 )
+    {
+        PERROR("Could not lock memory for Xen hypercall");
+        goto out1;
+    }
+
+    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
+    {
+       fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to"
+                    " rebuild the user-space tool set?\n",ret,errno);
+        goto out2;
+    }
+
+ out2: (void)munlock(op, nr_ops*sizeof(*op));
+ out1: return ret;
+}    
+
 
 /*
  * PFN mapping.
index b67458f521007e2591a67c2eaf62a46b2bcd5c6f..845fbc9f66ecada394001fef55c9a6543c46ba3f 100644 (file)
@@ -1186,7 +1186,8 @@ int get_page_type(struct pfn_info *page, u32 type)
                 nx &= ~PGT_va_mask;
                 nx |= type; /* we know the actual type is correct */
             }
-            else if ( unlikely((x & PGT_va_mask) != (type & PGT_va_mask)) )
+            else if ( ((type & PGT_va_mask) != PGT_va_mutable) &&
+                      ((type & PGT_va_mask) != (x & PGT_va_mask)) )
             {
                 /* This table is potentially mapped at multiple locations. */
                 nx &= ~PGT_va_mask;
@@ -1388,11 +1389,6 @@ int do_mmuext_op(
         switch ( op.cmd )
         {
         case MMUEXT_PIN_L1_TABLE:
-            /*
-             * We insist that, if you pin an L1 page, it's the first thing that
-             * you do to it. This is because we require the backptr to still be
-             * mutable. This assumption seems safe.
-             */
             type = PGT_l1_page_table | PGT_va_mutable;
 
         pin_page: